import * as vscode from 'vscode';
import ts from 'typescript';


const showTypesDisposable = vscode.commands.registerCommand('designpattern.showTypes', async () => {
    let document: vscode.TextDocument;
    if (vscode.window.activeTextEditor?.document.languageId === 'typescript') {
        document = vscode.window.activeTextEditor.document;
    } else if (vscode.workspace.workspaceFolders) {
        const uri = vscode.Uri.parse(await vscode.window.showInputBox({
            prompt: 'Enter TypeScript file path',
            value: vscode.workspace.workspaceFolders[0].uri.path
        }) || '');
        document = await vscode.workspace.openTextDocument(uri);
    }
    else {
        return;
    }

    if (document.languageId !== 'typescript') {
        return;
    }

    const typeDefinitions = collectAllTypeAlias(document)

    const items = typeDefinitions.map(def => ({
        label: def.name,
        description: `(Line ${def.line})`,
        def
    }));

    const selected = await vscode.window.showQuickPick(items, {
        placeHolder: 'Select a type to navigate to its definition'
    });

    if (selected) {
        const editor = await vscode.window.showTextDocument(document);
        const position = document.positionAt(selected.def.pos);
        editor.selection = new vscode.Selection(position, position);
        editor.revealRange(new vscode.Range(position, position));
    }
});


// concrete visitor
function collectAllTypeAlias(document: vscode.TextDocument): Array<{ name: string, pos: number, line: number }> {
    const typeDefinitions: Array<{ name: string, pos: number, line: number }> = [];

    const sourceFile = ts.createSourceFile(
        document.fileName,
        document.getText(),
        ts.ScriptTarget.Latest,
        true
    );

    const visitor: ts.Visitor = (node) => {
        if (ts.isTypeAliasDeclaration(node)) {
            const line = document.positionAt(node.getStart()).line + 1;
            typeDefinitions.push({
                name: node.name.getText(),
                pos: node.getStart(),
                line
            });
        }
        return ts.visitEachChild(node, visitor, undefined);
    };
    ts.visitNode(sourceFile, visitor);
    return typeDefinitions;
}

export function activate(context: vscode.ExtensionContext) {
    context.subscriptions.push(showTypesDisposable);
}


